'use strict'

module.exports = core;

// require: .js/.json/.node
// .js -> module.exports/exports
// .json -> JSON.parse
// any -> .js
const fs = require('fs')
const path = require('path')
const colors = require('colors/safe')
const log = require('@fobiz-cli/log')
const userHome = require('os').homedir()
const dotenv = require("dotenv");
const {program} = require('commander')

const pkg = require('../package.json')
const {DEFAULT_CLI_HOME} = require("./constant");
const {getSemverVersion} = require('@fobiz-cli/get-npm-info')
const exec = require('@fobiz-cli/exec')

const VERBOSE = 'verbose'

async function core(argv) {
  try {
    await prepare()
    registerCommand()
  } catch (e) {
    log.error(e.message)
    if (program.opts().debug) {
      console.log(e)
    }
  }
}

function checkPkgVersion() {
  log.notice('cli', pkg.version)
}

function checkRoot() {
  const rootCheck = require('root-check')
  rootCheck();
}

function checkUserHome() {
  if (!userHome || !fs.existsSync(userHome)) {
    throw new Error(colors.red('当前登录用户主目录不存在'))
  }
}

function checkEnv() {
  const dotenvPath = path.resolve(userHome, '.env-fobiz-cli')
  if (fs.existsSync(dotenvPath)) {
    dotenv.config({
      path: dotenvPath
    })
  }
  createDefaultConfig()
}

function createDefaultConfig() {
  /**
   *
  const cliConfig = {
    userHome
  }
  // 如果env文件中有CLI_HOME这个变量
  if (process.env.CLI_HOME) {
    cliConfig.cliHome = path.join(userHome, process.env.CLI_HOME)
  } else {
    cliConfig.cliHome = path.join(userHome, DEFAULT_CLI_HOME)
  }
  // @var CLI_HOME_PATH 脚手架所在目录
  process.env.CLI_HOME_PATH = cliConfig.cliHome
  */
  process.env.CLI_HOME_PATH = path.join(userHome, process.env.CLI_HOME ? process.env.CLI_HOME : DEFAULT_CLI_HOME)
}

async function checkGlobalUpdate() {
  // 1. 获取最新版本号和模块名
  const currentVersion = pkg.version
  const npmName = pkg.name
  // 2. 调用 npm API，拿到所有的版本号
  const lastVersion = await getSemverVersion(currentVersion, npmName)
  if (lastVersion) {
    log.warn('更新提示', `当前版本 ${currentVersion} 不是最新版，可以手动更新到最新版本：${lastVersion}，更新命令：npm install -g ${npmName}`)
  }
}

async function prepare() {
  checkPkgVersion()
  checkRoot()
  checkUserHome()
  checkEnv()
  await checkGlobalUpdate()
}

function registerCommand() {
  program.configureOutput({
    // Visibly override write routines as example!
    // writeOut: (str) => process.stdout.write(`[OUT] ${str}`),
    // writeErr: (str) => process.stdout.write(`[ERR] ${str}`),
  });
  program
      .name(Object.keys(pkg.bin)[0])
      .usage('<command> [options]')
      .version(pkg.version)
      .option('-d, --debug', '是否开启调试模式', false)
      .option('-tp, --targetPath <targetPath>', '是否指定本地调试文件路径')

  program
      // 此命令指定了init包的信息和项目的信息
      .command('init <projectName>')
      .description('init a project')
      .option('-f, --force', '是否强制初始化项目')
      // 动态加载初始化包 'init/my-init/your-init'
      .action(exec)
      .showHelpAfterError()
      .configureOutput({
        outputError: (str, write) => log.error(str)
      })

  // 监听debug模式
  program.on('option:debug', function() {
    log.level = process.env.LOG_LEVEL = VERBOSE
  })

  // 指定 targetPath
  program.on('option:targetPath', function() {
    process.env.CLI_TARGET_PATH = program.opts().targetPath
  })

  // 对未知命令监听
  program.on('command:*', function(commands) {
    const availableCommands = program.commands.map(cmd => cmd.name())
    log.error('未知命令:', colors.red(commands[0]))
    if (!availableCommands.length) return
    log.error('可用命令:', colors.red(availableCommands.join(', ')))
  })


  program.parse()

  if (program.args && program.args.length < 1) {
    program.outputHelp()
    program.helpInformation = function() {
      return ''
    }
    console.log()
  }
}
